package com.game.logic.fighting.pve;

import com.coment.message.BloodReturningMessage;
import com.coment.po.Game;
import com.coment.po.roles.Roles;
import com.game.dao.core.GameDao;
import com.game.dao.user.roles.RolesDao;
import com.game.logic.fighting.attrs.FightingLogic;
import com.game.logic.ranking.GameRakingService;
import com.game.logic.user.UserGameRolesDao;
import com.xs.action.exection.ActionException;
import com.xs.build.server.websocket.channel.ClientManager;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.concurrent.*;

@Slf4j
@Service
public class GameTime implements DisposableBean, InitializingBean {
    private ScheduledExecutorService virtualThreadPool;
    private ExecutorService taskExecutor;

    @Resource
    private GameDao gameDao;
    @Resource
    private RolesDao rolesDao;
    @Resource
    private GameServiceImpl gameServiceImpl;
    @Resource
    private GameRakingService rakingService;
    public static HashSet<Integer> activeRooms = new HashSet<>();
    @Resource
    private UserGameRolesDao userGameRolesDao;

    public void afterPropertiesSet() {
        activeRooms = new HashSet<>(this.gameDao.findAnchorInfoIdsByStartTimeNotNull());
        long start = 0L;
        this.virtualThreadPool = Executors.newSingleThreadScheduledExecutor(Thread.ofVirtual().name("game-timer-", start).factory());
        this.virtualThreadPool.scheduleAtFixedRate(this::gameTickProcess, 5L, 2L, TimeUnit.SECONDS);
        this.taskExecutor = Executors.newVirtualThreadPerTaskExecutor();
    }

    public void destroy() {
        if (this.virtualThreadPool != null) {
            this.virtualThreadPool.shutdown();
        }
        if (this.taskExecutor != null) {
            this.taskExecutor.shutdown();
        }
    }

    public void gameTickProcess() {
        HashSet<Integer> integers = new HashSet<>(activeRooms);
        for (Integer integer : integers) {
            this.taskExecutor.submit(() -> this.processGameRoom(integer));
        }
    }

    private void processGameRoom(Integer anchorInfoId) {
        synchronized (anchorInfoId + "") {
            boolean gameIsWin = userGameRolesDao.gameIsWin(anchorInfoId);
            if (gameIsWin) {
//                log.info("游戏胜利:{},等待结算中", anchorInfoId);
                return;
            }
            Game game = gameDao.findByIdMust(anchorInfoId);
            boolean b = this.gameServiceImpl.tryEndBattle(game);
            if (b) {
                log.info("游戏结束:{}", anchorInfoId);
                GameTime.activeRooms.remove(anchorInfoId);
                return;
            }

            // 怪物回血
            ConcurrentHashMap<String, Roles> rolesObjectPoolUpdate = new ConcurrentHashMap<>();
            for (String monsterId : game.monsterSet) {
                Roles roles = rolesDao.findByIdMust(monsterId);
                BloodReturningMessage bloodReturningMessage = FightingLogic.tryBloodReturning(roles);
                if (bloodReturningMessage != null && bloodReturningMessage.addValue > 0) {
                    log.info("怪物回血{}", bloodReturningMessage);
                    rolesObjectPoolUpdate.put(roles.getId(), roles);
                    ClientManager.sendMessageToClient(anchorInfoId, bloodReturningMessage);
                }
            }
            if (!rolesObjectPoolUpdate.isEmpty()) {
                rolesDao.saveAll(rolesObjectPoolUpdate.values());
            }

            for (String rolesId : game.userInfoIdSeat.values()) {
                Roles roles = rolesDao.findByIdMust(rolesId);
                try {
                    tryBloodReturning(roles);
                    this.rakingService.refreshTheRankingOfInternalCombatPower(anchorInfoId, roles);
                    this.rakingService.refreshTheInternalContributionRankingList(anchorInfoId, roles);
                } catch (Exception e) {
                    if (e instanceof ActionException) {
                        log.error("用户执行操作异常", e);
                    } else {
                        log.error("处理room[{}]-角色[{}]-[{}] 时发生异常: {}", anchorInfoId, roles.getUserInfoId(), roles.getCardId(), e.getMessage(), e);
                    }
                }
            }
        }
    }

    private void tryBloodReturning(Roles roles) {
        FightingLogic.tryBloodReturning(roles);
        this.rolesDao.save(roles);
    }
}
